const JSWebrtc = {
	Player: null,
	VideoElement: null,
	CreateVideoElements: function () {
		var elements = document.querySelectorAll(".jswebrtc");
		for (var i = 0; i < elements.length; i++) {
			new JSWebrtc.VideoElement(elements[i]);
		}
	},
	FillQuery: function (query_string, obj) {
		obj.user_query = {};
		if (query_string.length == 0) return;
		if (query_string.indexOf("?") >= 0) query_string = query_string.split("?")[1];
		var queries = query_string.split("&");
		for (var i = 0; i < queries.length; i++) {
			var query = queries[i].split("=");
			obj[query[0]] = query[1];
			obj.user_query[query[0]] = query[1];
		}
		if (obj.domain) obj.vhost = obj.domain;
	},
	ParseUrl: function (rtmp_url) {
		var a = document.createElement("a");
		a.href = rtmp_url
			.replace("rtmp://", "https://")
			.replace("webrtc://", "https://")
			.replace("rtc://", "https://");
		var vhost = a.hostname;
		var app = a.pathname.substr(1, a.pathname.lastIndexOf("/") - 1);
		var stream = a.pathname.substr(a.pathname.lastIndexOf("/") + 1);
		app = app.replace("...vhost...", "?vhost=");
		if (app.indexOf("?") >= 0) {
			var params = app.substr(app.indexOf("?"));
			app = app.substr(0, app.indexOf("?"));
			if (params.indexOf("vhost=") > 0) {
				vhost = params.substr(params.indexOf("vhost=") + "vhost=".length);
				if (vhost.indexOf("&") > 0) {
					vhost = vhost.substr(0, vhost.indexOf("&"));
				}
			}
		}
		if (a.hostname == vhost) {
			var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
			if (re.test(a.hostname)) vhost = "__defaultVhost__";
		}
		var schema = "rtmp";
		if (rtmp_url.indexOf("://") > 0) schema = rtmp_url.substr(0, rtmp_url.indexOf("://"));
		var port = a.port;
		if (!port) {
			if (schema === "http") {
				port = 80;
			} else if (schema === "https") {
				port = 443;
			} else if (schema === "rtmp") {
				port = 1935;
			} else if (schema === "webrtc" || schema === "rtc") {
				port = 1985;
			}
		}
		var ret = {
			url: rtmp_url,
			schema: schema,
			server: a.hostname,
			port: port,
			vhost: vhost,
			app: app,
			stream: stream
		};
		JSWebrtc.FillQuery(a.search, ret);
		return ret;
	},
	HttpPost: function (url, data) {
		return new Promise(function (resolve, reject) {
			var xhr = new XMLHttpRequest();
			xhr.onreadystatechange = function () {
				if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) {
					var respone = JSON.parse(xhr.responseText);
					xhr.onreadystatechange = new Function();
					xhr = null;
					resolve(respone);
				}
			};
			xhr.open("POST", url, true);
			xhr.timeout = 5e3;
			xhr.responseType = "text";
			xhr.setRequestHeader("Content-Type", "application/json");
			xhr.send(data);
		});
	}
};
if (document.readyState === "complete") {
	JSWebrtc.CreateVideoElements();
} else {
	document.addEventListener("DOMContentLoaded", JSWebrtc.CreateVideoElements);
}
JSWebrtc.VideoElement = (function () {
	"use strict";
	var VideoElement = function (element) {
		var url = element.dataset.url;
		if (!url) {
			throw "VideoElement has no `data-url` attribute";
		}
		var addStyles = function (element, styles) {
			for (var name in styles) {
				element.style[name] = styles[name];
			}
		};
		this.container = element;
		addStyles(this.container, {
			display: "inline-block",
			position: "relative",
			minWidth: "80px",
			minHeight: "80px"
		});
		this.video = document.createElement("video");
		this.video.width = 960;
		this.video.height = 540;
		addStyles(this.video, { display: "block", width: "100%" });
		this.container.appendChild(this.video);
		this.playButton = document.createElement("div");
		this.playButton.innerHTML = VideoElement.PLAY_BUTTON;
		addStyles(this.playButton, {
			zIndex: 2,
			position: "absolute",
			top: "0",
			bottom: "0",
			left: "0",
			right: "0",
			maxWidth: "75px",
			maxHeight: "75px",
			margin: "auto",
			opacity: "0.7",
			cursor: "pointer"
		});
		this.container.appendChild(this.playButton);
		var options = { video: this.video };
		for (var option in element.dataset) {
			try {
				options[option] = JSON.parse(element.dataset[option]);
			} catch (err) {
				options[option] = element.dataset[option];
			}
		}
		this.player = new JSWebrtc.Player(url, options);
		element.playerInstance = this.player;
		if (options.poster && !options.autoplay) {
			options.decodeFirstFrame = false;
			this.poster = new Image();
			this.poster.src = options.poster;
			this.poster.addEventListener("load", this.posterLoaded);
			addStyles(this.poster, {
				display: "block",
				zIndex: 1,
				position: "absolute",
				top: 0,
				left: 0,
				bottom: 0,
				right: 0
			});
			this.container.appendChild(this.poster);
		}
		if (!this.player.options.streaming) {
			this.container.addEventListener("click", this.onClick.bind(this));
		}
		if (options.autoplay) {
			this.playButton.style.display = "none";
		}
		if (this.player.audioOut && !this.player.audioOut.unlocked) {
			var unlockAudioElement = this.container;
			if (options.autoplay) {
				this.unmuteButton = document.createElement("div");
				this.unmuteButton.innerHTML = VideoElement.UNMUTE_BUTTON;
				addStyles(this.unmuteButton, {
					zIndex: 2,
					position: "absolute",
					bottom: "10px",
					right: "20px",
					width: "75px",
					height: "75px",
					margin: "auto",
					opacity: "0.7",
					cursor: "pointer"
				});
				this.container.appendChild(this.unmuteButton);
				unlockAudioElement = this.unmuteButton;
			}
			this.unlockAudioBound = this.onUnlockAudio.bind(this, unlockAudioElement);
			unlockAudioElement.addEventListener("touchstart", this.unlockAudioBound, false);
			unlockAudioElement.addEventListener("click", this.unlockAudioBound, true);
		}
	};
	VideoElement.prototype.onUnlockAudio = function (element, ev) {
		if (this.unmuteButton) {
			ev.preventDefault();
			ev.stopPropagation();
		}
		this.player.audioOut.unlock(
			function () {
				if (this.unmuteButton) {
					this.unmuteButton.style.display = "none";
				}
				element.removeEventListener("touchstart", this.unlockAudioBound);
				element.removeEventListener("click", this.unlockAudioBound);
			}.bind(this)
		);
	};
	VideoElement.prototype.onClick = function (ev) {
		if (this.player.isPlaying) {
			this.player.pause();
			this.playButton.style.display = "block";
		} else {
			this.player.play();
			this.playButton.style.display = "none";
			if (this.poster) {
				this.poster.style.display = "none";
			}
		}
	};
	VideoElement.PLAY_BUTTON =
		'<svg style="max-width: 75px; max-height: 75px;" ' +
		'viewBox="0 0 200 200" alt="Play video">' +
		'<circle cx="100" cy="100" r="90" fill="none" ' +
		'stroke-width="15" stroke="#fff"/>' +
		'<polygon points="70, 55 70, 145 145, 100" fill="#fff"/>' +
		"</svg>";
	VideoElement.UNMUTE_BUTTON =
		'<svg style="max-width: 75px; max-height: 75px;" viewBox="0 0 75 75">' +
		'<polygon class="audio-speaker" stroke="none" fill="#fff" ' +
		'points="39,13 22,28 6,28 6,47 21,47 39,62 39,13"/>' +
		'<g stroke="#fff" stroke-width="5">' +
		'<path d="M 49,50 69,26"/>' +
		'<path d="M 69,50 49,26"/>' +
		"</g>" +
		"</svg>";
	return VideoElement;
})();
JSWebrtc.Player = (function () {
	"use strict";
	var Player = function (url, options) {
		this.options = options || {};
		if (!url.match(/^webrtc?:\/\//)) {
			throw "JSWebrtc just work with webrtc";
		}
		if (!this.options.video) {
			throw "VideoElement is null";
		}
		this.urlParams = JSWebrtc.ParseUrl(url);
		this.pc = null;
		this.autoplay = !!options.autoplay || false;
		this.paused = true;
		if (this.autoplay) this.options.video.muted = true;
		this.startLoading();
	};
	Player.prototype.startLoading = function () {
		var _self = this;
		if (_self.pc) {
			_self.pc.close();
		}
		_self.pc = new RTCPeerConnection(null);
		_self.pc.ontrack = function (event) {
			_self.options.video["srcObject"] = event.streams[0];
		};
		_self.pc.addTransceiver("audio", { direction: "recvonly" });
		_self.pc.addTransceiver("video", { direction: "recvonly" });
		_self.pc
			.createOffer()
			.then(function (offer) {
				return _self.pc.setLocalDescription(offer).then(function () {
					return offer;
				});
			})
			.then(function (offer) {
				return new Promise(function (resolve, reject) {
					var port = _self.urlParams.port || 1985;
					var api = _self.urlParams.user_query.play || "/rtc/v1/play/";
					if (api.lastIndexOf("/") != api.length - 1) {
						api += "/";
					}
					var url = "https://" + _self.urlParams.server + ":" + port + api;
					for (var key in _self.urlParams.user_query) {
						if (key != "api" && key != "play") {
							url += "&" + key + "=" + _self.urlParams.user_query[key];
						}
					}
					var data = {
						api: url,
						streamurl: _self.urlParams.url,
						clientip: null,
						sdp: offer.sdp
					};
					// console.log("offer: " + JSON.stringify(data));
					JSWebrtc.HttpPost(url, JSON.stringify(data)).then(
						function (res) {
							// console.log("answer: " + JSON.stringify(res));
							resolve(res.sdp);
						},
						function (rej) {
							reject(rej);
						}
					);
				});
			})
			.then(function (answer) {
				return (
					_self.pc &&
					_self.pc.setRemoteDescription(
						new RTCSessionDescription({ type: "answer", sdp: answer })
					)
				);
			})
			.catch(function (reason) {
				throw reason;
			});
		if (this.autoplay) {
			this.play();
		}
	};
	Player.prototype.play = function (ev) {
		if (this.animationId) {
			return;
		}
		this.animationId = requestAnimationFrame(this.update.bind(this));
		this.paused = false;
	};
	Player.prototype.pause = function (ev) {
		if (this.paused) {
			return;
		}
		cancelAnimationFrame(this.animationId);
		this.animationId = null;
		this.isPlaying = false;
		this.paused = true;
		this.options.video.pause();
		if (this.options.onPause) {
			this.options.onPause(this);
		}
	};
	Player.prototype.stop = function (ev) {
		this.pause();
	};
	Player.prototype.destroy = function () {
		this.pause();
		this.pc && this.pc.close() && this.pc.destroy();
		this.audioOut && this.audioOut.destroy();
	};
	Player.prototype.update = function () {
		this.animationId = requestAnimationFrame(this.update.bind(this));
		if (this.options.video.readyState < 4) {
			return;
		}
		if (!this.isPlaying) {
			this.isPlaying = true;
			this.options.video.play();
			if (this.options.onPlay) {
				this.options.onPlay(this);
			}
		}
	};
	return Player;
})();

export {
	JSWebrtc
	// eslint-disable-next-line no-undef
	//instance as axios
};
